/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.datalayer.daoimpl;

import cz.fi.muni.diplomka.common.enumeration.ResearchType;
import cz.muni.fi.diplomka.datalayer.dao.ResearchDao;
import cz.muni.fi.diplomka.datalayer.entity.ResearchEntity;
import cz.muni.fi.diplomka.datalayer.util.DbConnector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

/**
 *
 * @author Jakub Kutil
 */
public class ResearchDaoImpl implements ResearchDao {

    @Override
    public void addResearch(ResearchEntity researchEntity) {
        if (researchEntity == null) {
            throw new IllegalArgumentException("Research Entity can not be null.");
        }

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            params.put("playerId", researchEntity.getPlayerId());
            params.put("researchType", researchEntity.getResearchType().toString());

            String query = "MATCH (Player:Player {id : {playerId}}) "
                    + "CREATE (Research: Research {researchType : {researchType}})<-[r:RESEARCHED]-(Player)";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public void editResearch(ResearchEntity researchEntity) {
        if (researchEntity == null) {
            throw new IllegalArgumentException("Research Entity can not be null.");
        }

        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();

        try (Transaction t = gds.beginTx()) {

            Map<String, Object> params = new HashMap<>();

            params.put("id", researchEntity.getPlayerId());
            params.put("researchType", researchEntity.getResearchType().toString());

            String query = "MATCH (Player:Player {id : {id} })-[r:RESEARCHED]->(Research:Research { researchType : {researchType}})"
                    + " SET Research.researchType = {researchType}";
            engine.execute(query, params);
            t.success();
        }
    }

    @Override
    public List<ResearchEntity> getAllResearchesOfPlayer(Long playerId) {
        if (playerId == null) {
            throw new IllegalArgumentException("Player Id can not be null.");
        }
        List<ResearchEntity> researchList = new ArrayList<>();
        GraphDatabaseService gds = DbConnector.getDBConnection();
        ExecutionEngine engine = DbConnector.getEngine();


        try (Transaction t = gds.beginTx()) {
            Map<String, Object> params = new HashMap<>();

            params.put("playerId", playerId);

            String query = "MATCH (Player:Player{ id : {playerId}})-[r:RESEARCHED]->(Research:Research) RETURN Research";
            ExecutionResult result = engine.execute(query, params);
            Iterator<Node> researches = result.columnAs("Research");
            while (researches.hasNext()) {
                Node node = researches.next();
                ResearchEntity researchEntity = new ResearchEntity();
                researchEntity.setPlayerId(playerId);
                researchEntity.setResearchType(ResearchType.valueOf(node.getProperty("researchType").toString()));

                researchList.add(researchEntity);
            }
            t.success();
        }
        return researchList;
    }
}
